package br.edu.ufabc.gtrnp.helppo.business;

import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimMethods.ADMIN_CREATE_REGION;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimMethods.ADMIN_REGION_QUERY;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.EXTERNAL_ADDRESS;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.LISTEN_IP;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.LISTEN_PORT;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.PERSIST;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_MASTER_FIRST;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_MASTER_LAST;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_MASTER_PASSWORD;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_NAME;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_UUID;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_X;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.REGION_Y;
import static br.edu.ufabc.gtrnp.helppo.util.RPCOpenSimParameters.SERVER_PASSWORD;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.hibernate.Query;
import org.hibernate.Session;

import br.edu.ufabc.gtrnp.helppo.business.exception.CriacaoRegiaoRPCException;
import br.edu.ufabc.gtrnp.helppo.business.exception.NenhumEspacoDisponivelException;
import br.edu.ufabc.gtrnp.helppo.persistence.entity.EspacoUtilizado;
import br.edu.ufabc.gtrnp.helppo.persistence.entity.Regiao;
import br.edu.ufabc.gtrnp.helppo.persistence.entity.Usuario;
import br.edu.ufabc.gtrnp.helppo.util.HelppoProperties;
import br.edu.ufabc.gtrnp.helppo.util.RpcClientSingleton;

public class RegiaoBusiness {

	private static RegiaoBusiness business = new RegiaoBusiness();
	private String nomeRegiao;
	private EspacoUtilizado espaco;

	private RegiaoBusiness() {
	}

	public static RegiaoBusiness getInstance() {
		return business;
	}

	public void criaRegiao(EspacoUtilizado espaco, String nomeRegiao,
			Usuario usuario) throws IOException,
			NenhumEspacoDisponivelException, CriacaoRegiaoRPCException {
		this.nomeRegiao = nomeRegiao;
		this.espaco = espaco;

		XmlRpcClient client = RpcClientSingleton.getInstance();
		try {
			client.execute(ADMIN_CREATE_REGION, parametrosCriacao(usuario));
		} catch (XmlRpcException e) {
			e.printStackTrace();
			throw new CriacaoRegiaoRPCException();
		}

	}

	private List<Hashtable<String, String>> parametrosCriacao(Usuario usuario)
			throws IOException, NenhumEspacoDisponivelException {
		Hashtable<String, String> parameters = new Hashtable<String, String>();
		ResourceBundle properties = HelppoProperties.getInstance();

		parameters.put(SERVER_PASSWORD, properties.getString(SERVER_PASSWORD));
		parameters.put(REGION_NAME, nomeRegiao);
		parameters.put(REGION_MASTER_FIRST, usuario.getUsername());
		parameters.put(REGION_MASTER_LAST, usuario.getLastname());
		parameters.put(REGION_MASTER_PASSWORD, usuario.getPasswordDecrypted());
		parameters.put(LISTEN_IP, properties.getString(LISTEN_IP));
		parameters
				.put(EXTERNAL_ADDRESS, properties.getString(EXTERNAL_ADDRESS));
		parameters.put(REGION_X, String.valueOf(espaco.getRegion_x()));
		parameters.put(REGION_Y, String.valueOf(espaco.getRegion_y()));
		parameters.put(PERSIST, "true");
		parameters.put(LISTEN_PORT, String.valueOf(espaco.getListen_port()));

		List<Hashtable<String, String>> list = new ArrayList<Hashtable<String, String>>();
		list.add(parameters);

		return list;
	}

	@SuppressWarnings("unchecked")
	public List<Regiao> buscaListaRegioes(Usuario usuario) throws IOException {

		GenericDAO dao = new GenericDAO();
		Session session = dao.getCurrentSession();

		String hql = "from Regiao where owner_uuid =:a order by regionName";
		Query query = session.createQuery(hql);
		query.setString("a", usuario.getUUID());
		List lista = query.list();

		List<Regiao> regioes = new ArrayList<Regiao>();
		for (Object object : lista) {
			Regiao regiao = (Regiao) object;
			if(verificaStatusRegiao(regiao))
				regiao.setStatus("Online");
			else
				regiao.setStatus("Offline");
			regioes.add(regiao);
		}

		return regioes;
	}

	@SuppressWarnings("unchecked")
	public boolean verificaStatusRegiao(Regiao regiao) throws IOException{

		HashMap<String, Object> retorno = null;
		XmlRpcClient client = RpcClientSingleton.getInstance();
		try {
			retorno = (HashMap<String, Object>) client.execute(
					ADMIN_REGION_QUERY, parameterConsultaStatus(regiao));
		} catch (XmlRpcException e) {
			e.printStackTrace();
			return false;
		}

		if (retorno != null) {
			Integer health = (Integer)retorno.get("health");
			
			if (health != null && health == 1)
				return true;
		}

		return false;
	}

	private List<Hashtable<String, String>> parameterConsultaStatus(
			Regiao regiao) throws IOException {
		Hashtable<String, String> parameters = new Hashtable<String, String>();

		ResourceBundle properties = HelppoProperties.getInstance();

		parameters.put(REGION_UUID, regiao.getOriginUUID());
		parameters.put(SERVER_PASSWORD, properties.getString(SERVER_PASSWORD));

		List<Hashtable<String, String>> list = new ArrayList<Hashtable<String, String>>();
		list.add(parameters);

		return list;
	}
}
